
;--- IClassFactory implementation for IDirectDraw
;--- required if CoCreateInstance is used to create an IDirectDraw object

	.386
if ?FLAT
	.MODEL FLAT, stdcall
else
	.MODEL SMALL, stdcall
endif
	option casemap:none
	option proc:private

	include windef.inc
	include winbase.inc
	include ddraw.inc
	include dddraw.inc
	include macros.inc

if ?DD7
DirectDrawCreateEx	proto :ptr, :ptr dword, :ptr IID, :LPUNKNOWN
endif

	.DATA
        
g_DllRefCount dd 0

	.CONST
        
CClassFactoryVtbl label IClassFactoryVtbl
	dd QueryInterface_,	AddRef_, Release_, CreateInstance_, LockServer_

CClassFactory struct
vtbl		dd ?
ObjRefCount dd ?
CClassFactory ends

Create@CClassFactory proto
AddRef_  proto :ptr CClassFactory
Release_ proto :ptr CClassFactory

CLSID_DirectDraw	GUID <0D7B70EE0h,4340h,11CFh,<0B0h, 63h,00h, 20h,0AFh,0C2h,0CDh, 35h>>
if ?DD7
CLSID_DirectDraw7	GUID <03c305196h,50dbh,11d3h,< 9ch,0feh,00h,0c0h, 4fh,0d9h, 30h,0c5h>>
;;IID_IDirectDraw7	GUID <015e65ec0h, 03b9ch,  11d2h, <0b9h,  2fh,  00h,  60h,  97h,  97h, 0eah,  5bh>>
endif
IID_IUnknown     	GUID <00000000,0000,0000,<0C0h,00,00,00,00,00,00,46h>>
IID_IClassFactory	GUID <00000001,0000,0000,<0C0h,00,00,00,00,00,00,46h>>

        .CODE

DllGetClassObject proc public uses esi edi pClsid:REFGUID, riid:REFGUID, ppv:ptr DWORD

local	pClassFactory:dword

	mov edi,offset CLSID_DirectDraw
	mov esi,pClsid
	mov ecx,4
	repz cmpsd
	jz found
if ?DD7
	mov edi,offset CLSID_DirectDraw7
	mov esi,pClsid
	mov ecx,4
	repz cmpsd
	jz found
endif
	mov eax, CLASS_E_CLASSNOTAVAILABLE
	jmp exit
found:
	invoke Create@CClassFactory
	.if (!eax)
		mov eax, E_OUTOFMEMORY
		jmp exit
	.endif
	mov pClassFactory, eax
	invoke vf(pClassFactory,IClassFactory,QueryInterface),riid,ppv
	push eax
	invoke vf(pClassFactory,IClassFactory,Release)
	pop eax
exit:
	ret
	align 4

DllGetClassObject endp

Create@CClassFactory PROC public

	invoke LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, sizeof CClassFactory
	and eax, eax
	jz exit
	mov [eax].CClassFactory.vtbl,OFFSET CClassFactoryVtbl
	mov [eax].CClassFactory.ObjRefCount, 1
	inc g_DllRefCount
exit:
	ret
	align 4

Create@CClassFactory ENDP

;------ destructor ClassFactory, return void

Destroy_ PROC this_:ptr CClassFactory

	invoke LocalFree, this_
	dec g_DllRefCount
	ret
	align 4
Destroy_ ENDP

QueryInterface_ PROC uses esi edi this_:ptr CClassFactory ,riid:ptr IID,ppv:ptr

	mov edx, this_
	mov edi,offset IID_IUnknown
	mov esi,riid
	mov ecx,4
	repz cmpsd
	jz found
	mov edi,offset IID_IClassFactory
	mov esi,riid
	mov ecx,4
	repz cmpsd
	jz found
	mov ecx,ppv
	mov dword ptr [ecx],0
	mov eax,E_NOINTERFACE
	jmp exit
found:
	mov ecx,ppv
	mov [ecx], edx
	invoke AddRef_, edx
	mov eax, S_OK
exit:
	ret
	align 4

QueryInterface_ ENDP


AddRef_ PROC this_:ptr CClassFactory

	mov ecx, this_
	mov eax, [ecx].CClassFactory.ObjRefCount
	inc [ecx].CClassFactory.ObjRefCount
	ret
	align 4

AddRef_ ENDP


Release_ PROC this_:ptr CClassFactory

	mov ecx, this_
	mov eax,[ecx].CClassFactory.ObjRefCount
	dec [ecx].CClassFactory.ObjRefCount
	.if (eax == 1)
		invoke Destroy_, this_
		xor eax,eax
	.endif
	ret
	align 4

Release_ ENDP


CreateInstance_ PROC pThis:ptr CClassFactory, pUnkOuter:LPUNKNOWN,
					riid:ptr IID,ppObject:ptr LPUNKNOWN

local	pObject:ptr objectname

	mov eax, ppObject
	mov DWORD PTR [eax], NULL

if 0;?AGGREGATION
;------------- if pUnkOuter != NULL riid MUST be IID_IUnknown!
	.if (pUnkOuter != NULL)
		invoke IsEqualGUID, riid, addr IID_IUnknown
		.if (eax == FALSE)
			DebugOut "IClassFactory::CreateInstance failed (riid != IID_IUnknown)"
			return CLASS_E_NOAGGREGATION
		.endif
	.endif
else
	.if (pUnkOuter != NULL)
		return CLASS_E_NOAGGREGATION
	.endif
endif

;--- call constructor

if ?DD7
	push esi
	push edi
	mov edi,offset IID_IDirectDraw7
	mov esi,riid
	mov ecx,4
	repz cmpsd
	pop edi
	pop esi
	jnz @F
	invoke DirectDrawCreateEx, 0, addr pObject, riid, pUnkOuter
	jmp exit
@@:        
endif

	invoke DirectDrawCreate, 0, addr pObject, pUnkOuter
	.if (eax != DD_OK)
		jmp exit
	.endif

;--- get the right interface

	invoke vf(pObject,IUnknown,QueryInterface), riid, ppObject
	push eax
	invoke vf(pObject,IUnknown,Release)
	pop eax    
exit:
	ret
	align 4

CreateInstance_ ENDP


LockServer_ PROC pThis:ptr CClassFactory, bLockServer:DWORD

	.if (bLockServer)
		inc g_DllRefCount
	.else
		dec g_DllRefCount
	.endif
	return S_OK
	align 4

LockServer_ ENDP

	END

